<template>
  <div ref="container" class="scene-container"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";
import textureImage from "../assets/473ee8a12b93506ecb0ae4f17ce9a188.png";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入GSAP
import gsap from "gsap";
//导入dat.gui
import * as dat from "dat.gui";

import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
//目标:灯光与阴影
/**
 * 灯光与阴影
 * 1. 材质要满足能够对光照有反应
 * 2.设置渲染器开启阴影的计算renderer.shadowMap.enabled = true;
 * 3.设置光照投射阴影directionalLight.castShadow = true;
 * 4.设置物体投射阴影 sphere.castShadow = true;
 * 5.设置物体的接收阴影 plane.receiveShadow = true;
 */

//给当前组件一个名称，使用defineOptions定义
defineOptions({
  name: "ThreeScene",
});

const container = ref<HTMLElement>();
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let cube: THREE.Mesh;
//声明轨道控制器
let controls: OrbitControls;
// 创建一个 GUI 实例
const gui = new dat.GUI();

const initScene = () => {
  //创建场景
  scene = new THREE.Scene();
  //创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  //创建渲染器
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 开启阴影
  renderer.shadowMap.enabled = true;
  container.value?.appendChild(renderer.domElement);
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.05;
  //创建坐标轴
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);
  camera.position.set(0, 0, 10);
  scene.add(camera);
  const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
  const material = new THREE.MeshStandardMaterial({
    color: "#fff",
    // side: THREE.DoubleSide,
  });
  const sphere = new THREE.Mesh(sphereGeometry, material);
  // 设置物体投射阴影
  sphere.castShadow = true;
  scene.add(sphere);
  //创建平面
  const planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10);
  const plane = new THREE.Mesh(planeGeometry, material);
  plane.position.set(0, -1, 0);
  plane.rotation.x = -Math.PI / 2; //旋转90°铺平
  // 设置物体接收阴影
  plane.receiveShadow = true;
  scene.add(plane);

  //环境光
  const light = new THREE.AmbientLight(0xffffff, 0.8);
  scene.add(light);
  // //灯光--平行光--直线光源
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1); //设置平行光颜色和强度
  directionalLight.position.set(10, 10, 10);
  // 设置平行光投射阴影
  directionalLight.castShadow = true;
  // 设置平行光投射阴影的模糊等级
  directionalLight.shadow.radius = 20;
  //设置阴影贴图的分辨率
  directionalLight.shadow.mapSize.set(4096, 4096);
  //设置平行光投射相机的属性
  directionalLight.shadow.camera.top = 10;
  directionalLight.shadow.camera.bottom = -10;
  directionalLight.shadow.camera.left = -10;
  directionalLight.shadow.camera.right = 10;
  directionalLight.shadow.camera.near = 0.5;
  directionalLight.shadow.camera.far = 500;
  scene.add(directionalLight);
  //修改near
  gui
    .add(directionalLight.shadow.camera, "near", 0, 10)
    .min(0)
    .max(100)
    .step(0.01)
    .name("near")
    .onChange((value) => {
      directionalLight.shadow.camera.updateProjectionMatrix(); //更新相机
    });
  //修改平行光源的位置通过gui
  gui
    .add(directionalLight.position, "x", -5, 5)
    .min(-10)
    .max(10)
    .step(0.01)
    .name("平行光x轴");
  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  animate();
};
onMounted(() => {
  initScene();
});
// 添加动画循环函数
const animate = () => {
  requestAnimationFrame(animate);
  // 更新控制器
  controls.update();
  // 渲染场景
  renderer.render(scene, camera);
};
</script>
